<template>
  <div class="prefixCls" :style="{ width: containerWidth }">
    <textarea :id="tinymceId" ref="elRef" :style="{ visibility: 'hidden' }" />
  </div>
</template>

<script setup>
import tinymce from "tinymce/tinymce";
import "tinymce/themes/silver";
import "tinymce/icons/default/icons";
import "tinymce/plugins/advlist";
import "tinymce/plugins/anchor";
import "tinymce/plugins/autolink";
import "tinymce/plugins/autosave";
import "tinymce/plugins/code";
import "tinymce/plugins/codesample";
import "tinymce/plugins/directionality";
import "tinymce/plugins/fullscreen";
import "tinymce/plugins/hr";
import "tinymce/plugins/insertdatetime";
import "tinymce/plugins/link";
import "tinymce/plugins/lists";
import "tinymce/plugins/media";
import "tinymce/plugins/nonbreaking";
import "tinymce/plugins/noneditable";
import "tinymce/plugins/pagebreak";
import "tinymce/plugins/paste";
import "tinymce/plugins/preview";
// import "tinymce/plugins/print";
import "tinymce/plugins/save";
import "tinymce/plugins/searchreplace";
import "tinymce/plugins/spellchecker";
import "tinymce/plugins/tabfocus";
import "tinymce/plugins/template";
import "tinymce/plugins/textpattern";
import "tinymce/plugins/visualblocks";
import "tinymce/plugins/visualchars";
import "tinymce/plugins/wordcount";
import "tinymce/plugins/image";
import "tinymce/plugins/table";
// import "tinymce/plugins/toc";

import {
  computed,
  nextTick,
  ref,
  unref,
  watch,
  onDeactivated,
  onBeforeUnmount,
  getCurrentInstance
} from "vue";
import { toolbar, plugins, fontFormats } from "./tinymce";
import { buildShortUUID } from "@/utils/uuid";
import { bindHandlers } from "./helper";
import { onMountedOrActivated } from "@/hooks/useOnMountedOrActivated";
import { isNumber } from "@/utils/util";

const props = defineProps({
  options: {
    type: Object,
    default: () => {}
  },
  value: {
    type: String
  },
  toolbar: {
    type: Array,
    default: toolbar
  },
  plugins: {
    type: Array,
    default: plugins
  },
  modelValue: {
    type: String
  },
  height: {
    type: [Number, String],
    required: false,
    default: "calc(100vh - 60px)"
  },
  width: {
    type: [Number, String],
    required: false,
    default: "auto"
  },
  showImageUpload: {
    type: Boolean,
    default: true
  }
});
const emits = defineEmits([
  "change",
  "update:modelValue",
  "inited",
  "init-error",
  "imgUpload"
]);
const { attrs } = getCurrentInstance();
const tinymceId = ref(buildShortUUID("tiny-vue"));

const containerWidth = computed(() => {
  const width = props.width;
  if (isNumber(width)) {
    return `${width}px`;
  }
  return width;
});

const editorRef = ref(null);
const fullscreen = ref(false);
const elRef = ref(null);
// const tinymceContent = computed(() => props.modelValue);

const initOptions = computed(() => {
  const { height, options, toolbar, plugins } = props;
  return {
    selector: `#${unref(tinymceId)}`,

    height,
    branding: false,
    default_link_target: "_blank",
    link_title: false,
    object_resizing: false, //是否允许用户调整插入的图像和其他嵌入对象的大小
    auto_focus: true,
    resize: false,
    placeholder: "请输入内容", // 占位符
    // 工具栏，插件相关
    toolbar,
    menubar: "file edit insert view format table",
    toolbar_sticky: true,
    plugins,
    // 皮肤、字体、语言
    language_url: "/resource/tinymce/langs/zh_CN.js",
    language: "zh_CN",
    skin: "oxide",
    skin_url: "/resource/tinymce/skins/ui/oxide",
    content_css: "/resource/tinymce/skins/ui/oxide/content.min.css",
    fontsize_formats: "12px 14px 16px 18px 20px 22px 24px 26px 36px 48px 56px", // 工具栏自定义字体大小选项
    font_formats: fontFormats,
    // icons: "custom", // 自定义图标名称
    // icons_url: "/resource/tinymce/icons/icons.js", // 自定义图标路径

    // 文件
    paste_block_drop: true, // 禁用将内容拖放到编辑器中
    images_upload_handler: handleImgUpload,
    images_upload_url: "/upload-image", // 上传图片的API地址
    automatic_uploads: true, // 启用自动上传
    paste_data_images: true, // 启用粘贴图片上传
    images_file_types: "jpeg,jpg,png,gif,bmp,webp", // 准许的图片格式

    // autosave 插件配置，需引入插件 autosave
    // autosave_ask_before_unload: true, // 阻止有内容时浏览器阻塞行为, 默认 true
    // autosave_interval: "3s", // 设置自动保存为草稿时间 单位只能为s
    // autosave_prefix: `editor_`, // 设置自动保存为草稿时前缀 本地localStorage中存储
    // autosave_retention: "300m", // 自动草稿的有效期 单位只能为m(分钟)

    //
    content_style: `
          img                       { max-width:100%; display:block;height:auto; }
          a                         { text-decoration: none; }
          p                         { line-height:1.6; margin: 0px; }
          table                     { word-wrap:break-word; word-break:break-all;max-width:100%; border:none; border-color:#999; }
          .mce-object-iframe        { width:100%; box-sizing:border-box; margin:0; padding:0; }
          ul,ol                     { list-style-position:inside; }
          `,
    table_class_list: [
      { title: "None", value: "" },
      { title: "表头", value: "table_header" },
      { title: "白色", value: "table_row_white_background" },
      { title: "灰色", value: "table_row_gray_background" }
    ],

    ...options,
    setup: editor => {
      editorRef.value = editor;
      editor.on("init", e => {
        // Prism.highlightAll();

        return initSetup(e);
      });
    }
  };
});

// const disabled = computed(() => {
//   const { options } = props;
//   const getdDisabled = options && Reflect.get(options, "readonly");
//   const editor = unref(editorRef);
//   if (editor) {
//     editor.setMode(getdDisabled ? "readonly" : "design");
//   }
//   return getdDisabled ?? false;
// });

watch(
  () => attrs.disabled,
  () => {
    const editor = unref(editorRef);
    if (!editor) {
      return;
    }
    editor.setMode(attrs.disabled ? "readonly" : "design");
  }
);

onMountedOrActivated(() => {
  if (!initOptions.value.inline) {
    tinymceId.value = buildShortUUID("tiny-vue");
  }
  nextTick(() => {
    setTimeout(() => {
      initEditor();
    }, 30);
  });
});

onBeforeUnmount(() => {
  destory();
});

onDeactivated(() => {
  destory();
});

function destory() {
  if (tinymce !== null) {
    // tinymce?.remove?.(unref(initOptions).selector!);
  }
}

function initSetup(e) {
  const editor = unref(editorRef);
  if (!editor) {
    return;
  }
  const value = props.modelValue || "";

  editor.setContent(value);
  bindModelHandlers(editor);
  bindHandlers(e, attrs, unref(editorRef));
}

function initEditor() {
  const el = unref(elRef);
  if (el) {
    el.style.visibility = "";
  }
  tinymce
    .init(unref(initOptions))
    .then(editor => {
      emits("inited", editor);
    })
    .catch(err => {
      emits("init-error", err);
    });
}

function setValue(editor, val, prevVal) {
  if (
    editor &&
    typeof val === "string" &&
    val !== prevVal &&
    val !== editor.getContent({ format: attrs.outputFormat })
  ) {
    editor.setContent(val);
  }
}

function bindModelHandlers(editor) {
  const modelEvents = attrs.modelEvents ? attrs.modelEvents : null;
  const normalizedEvents = Array.isArray(modelEvents)
    ? modelEvents.join(" ")
    : modelEvents;

  watch(
    () => props.modelValue,
    (val, prevVal) => {
      setValue(editor, val, prevVal);
    }
  );

  watch(
    () => props.value,
    (val, prevVal) => {
      setValue(editor, val, prevVal);
    },
    {
      immediate: true
    }
  );

  editor.on(normalizedEvents || "change keyup undo redo", () => {
    const content = editor.getContent({ format: attrs.outputFormat });
    emits("update:modelValue", content);
    emits("change", content);
  });

  editor.on("FullscreenStateChanged", e => {
    fullscreen.value = e.state;
  });
}

// 图片上传自定义逻辑
// function handleImgUpload(blobInfo, success, failure, progress) {
function handleImgUpload(blobInfo, success, failure) {
  // console.log("blobInfo", blobInfo.blob(), blobInfo.filename());
  // console.log("success", success);
  // console.log("failure", failure);
  // console.log("progress", progress);
  // 调用服务端上传接口
  // const { type: fileType, name: fileName } = blobInfo.blob();
  const { name: fileName } = blobInfo.blob();

  const formData = new FormData();
  formData.append("image", blobInfo.blob(), fileName);
  // console.log("formData", formData);

  emits("imgUpload", formData, success, failure);
  // success()
  // 模拟上传
  // xxxx 自定义上传逻辑
}
</script>

<style lang="scss" scoped>
.prefixCls {
  position: relative;
  line-height: normal;
}
textarea {
  z-index: -1;
  visibility: hidden;
}
</style>
